package com.ys.nms.module.business.controller.admin.redData;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.Session;
import com.ys.nms.module.business.libreApi.config.LibreNmsConfigFactory;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
@AllArgsConstructor
public class RrdMultiColumnReader {
    private final SshConfig sshConfig;
    private final LibreNmsConfigFactory configFactory;

    /**
     * 查询多列RRD数据
     */
    public RrdMultiQueryResult queryMultiColumnRrdData(RrdQueryParams params) {
        try {
            if (!validateParams(params)) {
                return new RrdMultiQueryResult("参数验证失败", params);
            }

            // 构建远程命令
            String rrdFilePath = buildRrdFilePath(params.getDeviceIp(), params.getRrdFile());
            String command = String.format("rrdtool fetch %s AVERAGE --start %s --end %s",
                    rrdFilePath, params.getStartTime(), params.getEndTime());

            log.info("执行远程RRDtool命令: {}", command);

            // 执行命令并获取输出
            List<String> outputLines = executeRemoteCommand(command);

            // 解析多列数据
            List<RrdMultiDataPoint> dataPoints = parseMultiColumnRrdOutput(outputLines);
            List<String> columnNames = extractColumnNames(outputLines);

            return new RrdMultiQueryResult(dataPoints, params, columnNames);

        } catch (Exception e) {
            log.error("查询多列RRD数据时发生错误: {}", e.getMessage(), e);
            return new RrdMultiQueryResult("查询失败: " + e.getMessage(), params);
        }
    }

    /**
     * 解析多列RRD输出
     */
    private List<RrdMultiDataPoint> parseMultiColumnRrdOutput(List<String> outputLines) {
        List<RrdMultiDataPoint> dataPoints = new ArrayList<>();

        if (outputLines.isEmpty()) {
            return dataPoints;
        }

        // 提取列名
        List<String> columnNames = extractColumnNames(outputLines);

        // 解析数据行
        boolean first = true;
        for (String line : outputLines) {
            // 跳过标题行和空行
            if (first) {
                first = false;
                continue;
            }
//            if (line.startsWith(" ") || line.contains("timestamp") || line.isEmpty()) {
//                continue;
//            }

            RrdMultiDataPoint dataPoint = parseMultiColumnDataLine(line, columnNames);
            if (dataPoint != null) {
                dataPoints.add(dataPoint);
            }
        }

        return dataPoints;
    }

    /**
     * 提取列名
     */

    public List<String> extractColumnNames(List<String> outputLines) {
        if (outputLines.size() > 1) {
            String headerLine = outputLines.get(0).trim(); // 假设第1行是列名
            return Arrays.stream(headerLine.split("\\s+"))
                    .filter(name -> !name.isEmpty())
                    .collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 解析多列数据行
     */
    private RrdMultiDataPoint parseMultiColumnDataLine(String line, List<String> columnNames) {
        try {
            String[] parts = line.split(":");
            if (parts.length != 2) {
                log.warn("数据行格式错误parseMultiColumnDataLine: {}", line);
                return null;
            }

            // 解析时间戳
            Long timestamp = Long.parseLong(parts[0].trim());
            RrdMultiDataPoint dataPoint = new RrdMultiDataPoint(timestamp);

            // 解析多列数据
            String valuesStr = parts[1].trim();
            String[] valueArray = valuesStr.split("\\s+");

            // 确保列数和值数匹配
            int columnCount = Math.min(columnNames.size(), valueArray.length);

            for (int i = 0; i < columnCount; i++) {
                if (valueArray[i].length() > 4) {
                    String valueStr = valueArray[i].substring(0,4);
//                String value = parseValue(valueStr);
                    dataPoint.addMetric(columnNames.get(i), valueStr);
                }
            }

            return dataPoint;

        } catch (NumberFormatException e) {
            log.warn("解析多列数据行失败: {}", line);
            return null;
        }
    }

    /**
     * 解析单个数值
     */
    private Double parseValue(String valueStr) {
        if ("-nan".equalsIgnoreCase(valueStr) || "nan".equalsIgnoreCase(valueStr)) {
            return Double.NaN;
        } else {
            try {
                return Double.parseDouble(valueStr);
            } catch (NumberFormatException e) {
                log.warn("数值解析失败: {}", valueStr);
                return Double.NaN;
            }
        }
    }

    /**
     * 获取指定列的有效数据
     */
    public List<RrdMultiDataPoint> getValidDataForColumn(RrdMultiQueryResult result, String columnName) {
        return result.getDataPoints().stream()
                .filter(point -> point.isMetricValid(columnName))
                .collect(Collectors.toList());
    }

    /**
     * 获取所有有效数据（至少有一列有效）
     */
    public List<RrdMultiDataPoint> getAnyValidData(RrdMultiQueryResult result) {
        return result.getDataPoints().stream()
                .filter(RrdMultiDataPoint::hasValidData)
                .collect(Collectors.toList());
    }

    /**
     * 计算指定列的统计信息
     */
//    public Map<String, Object> calculateColumnStats(RrdMultiQueryResult result, String columnName) {
//        List<String> validValues = result.getDataPoints().stream()
//                .filter(point -> point.isMetricValid(columnName))
//                .map(point -> point.getMetric(columnName))
//                .collect(Collectors.toList());
//
//        if (validValues.isEmpty()) {
//            return Map.of(
//                    "count", 0,
//                    "message", "没有有效数据"
//            );
//        }
//
//        double min = validValues.stream().mapToDouble(Double::doubleValue).min().orElse(0);
//        double max = validValues.stream().mapToDouble(Double::doubleValue).max().orElse(0);
//        double avg = validValues.stream().mapToDouble(Double::doubleValue).average().orElse(0);
//        double sum = validValues.stream().mapToDouble(Double::doubleValue).sum();
//
//        return Map.of(
//                "count", validValues.size(),
//                "min", min,
//                "max", max,
//                "average", avg,
//                "sum", sum,
//                "minFormatted", String.format("%.6f", min),
//                "maxFormatted", String.format("%.6f", max),
//                "averageFormatted", String.format("%.6f", avg)
//        );
//    }

    // 以下方法保持不变，只需要调用对应的多列版本
    private boolean validateParams(RrdQueryParams params) {
        if (params.getDeviceIp() == null || params.getDeviceIp().trim().isEmpty()) {
            log.error("设备IP不能为空");
            return false;
        }
        if (params.getRrdFile() == null || params.getRrdFile().trim().isEmpty()) {
            log.error("RRD文件名不能为空");
            return false;
        }
        return true;
    }

    private String buildRrdFilePath(String deviceIp, String rrdFile) {
        // 根据你的实际路径构建
        return String.format("/home/fengli/librenms-master/examples/compose/librenms/rrd/%s/%s",
                deviceIp, rrdFile);
    }


    private List<String> executeRemoteCommand(String command) throws Exception {
        //判断是本地环境还剩正式环节
        if (isLocalProfile()) {
            return queryRrdData(command);
        }
        Process process = new ProcessBuilder(command).start();
        List<String> outputLines = readProcessOutput(process);
        if (process.waitFor() != 0) {
            throw new Exception("RRDtool命令执行失败");
        }
        return outputLines;
    }

    public List<String> queryRrdData(String command) {
        Session session = null;
        ChannelExec channel = null;

        try {

            log.info("执行远程RRDtool命令: {}", command);
            // 创建SSH会话
            session = sshConfig.createSession();
            session.connect();

            // 执行命令
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            channel.setInputStream(null);

            InputStream in = channel.getInputStream();
            channel.connect();

            // 读取命令输出
            List<String> outputLines = readRemoteOutput(in);

            // 检查命令执行状态
            int exitStatus = channel.getExitStatus();
            if (exitStatus != 0) {
                throw new Exception("WINDOWS远程RRDtool命令执行失败，退出码: " + exitStatus +  "命令:" + command);
            }
            return outputLines;
        } catch (Exception e) {
            log.error("通过SSH查询RRD数据时发生错误: {}", e.getMessage(), e);
        } finally {
            // 清理资源
            if (channel != null && channel.isConnected()) {
                channel.disconnect();
            }
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
        return new ArrayList<>();
    }

    private List<String> readProcessOutput(Process process) throws Exception {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String trimmedLine = line.trim();
                if (!trimmedLine.isEmpty()) {
                    lines.add(trimmedLine);
                }
            }
        }
        return lines;
    }

    /**
     * 读取远程命令输出
     */
    private List<String> readRemoteOutput(InputStream in) throws Exception {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String trimmedLine = line.trim();
                if (!trimmedLine.isEmpty()) {
                    lines.add(trimmedLine);
                }
            }
        }
        return lines;
    }


    public boolean isLocalProfile() {
        String activeProfile = configFactory.getActiveProfile();
        if (activeProfile.equals("local")) {
            return true;
        } else {
            return false;
        }
    }

}